home *** CD-ROM | disk | FTP | other *** search
/ Sprite 1984 - 1993 / Sprite 1984 - 1993.iso / src / machserver / 1.098 / sync / sync.h < prev    next >
C/C++ Source or Header  |  1991-08-06  |  24KB  |  935 lines

  1. /*
  2.  * sync.h --
  3.  *
  4.  *     Definitions of routines for the synchronization module.
  5.  *     The synchronization module provides locks and condition
  6.  *     variables to other modules, plus a low level binary semaphore 
  7.  *    needed to synchronize with interrupt handlers.
  8.  *
  9.  *    The behavior of the sync module can be modified using compiler 
  10.  *    variables. These variables will change the structure of locks and
  11.  *    how the locks are used. In general it is not a good idea to link
  12.  *    modules that have been compiled with different versions of locks.
  13.  *    
  14.  *        <default> -     semaphores and locks have fields that contain a
  15.  *              character string name, the pc where the lock was
  16.  *             last locked, and a pointer to the pcb of the last
  17.  *             lock holder. The locking operation is slower because
  18.  *             these fields must be updated.
  19.  *
  20.  *        CLEAN_LOCK - locks do not contain any extra fields. This version
  21.  *                 of locks is intended for benchmarking the kernel.
  22.  *    
  23.  *        LOCKREG    - locks are registered so that the information stored
  24.  *             in them can be retrieved. In addition to the fields
  25.  *             in the default version of locks, a count of hits
  26.  *             and misses on each lock is kept. Lock registration
  27.  *             must be done when the lock is created and destroyed.
  28.  *             The locking operation is slower due to the hit/miss
  29.  *             counters.  A count is kept for each spin lock that
  30.  *             records the number of times a processor spun waiting
  31.  *             for the lock.
  32.  *
  33.  *        LOCKDEP    - Each lock keeps a list of locks that were held when
  34.  *             it was locked in addition to the information kept
  35.  *             in the LOCKREG version. Locks compiled with LOCKDEP
  36.  *                 will get very large. This information can be used to 
  37.  *             construct a graph of the locking behavior of the
  38.  *             kernel. Locking and unlocking is slowed down due
  39.  *             to the necessity of recording previously held lock.
  40.  *
  41.  *
  42.  * Copyright 1986 Regents of the University of California
  43.  * All rights reserved.
  44.  *
  45.  * $Header: /sprite/src/kernel/sync/RCS/sync.h,v 9.11 91/08/06 17:00:04 kupfer Exp $ SPRITE (Berkeley)
  46.  */
  47.  
  48. #ifndef _SYNC
  49. #define _SYNC
  50.  
  51. #include <sprite.h>
  52. #include <list.h>
  53.  
  54. #ifdef KERNEL
  55. #include <syncTypes.h>
  56. #include <mach.h>
  57. #include <proc.h>
  58. #else
  59. #include <kernel/syncTypes.h>
  60. #include <kernel/mach.h>
  61. #include <kernel/proc.h>
  62. #endif /* KERNEL */
  63.  
  64. /*
  65.  * These include files are needed by the SysV sema support.
  66.  */
  67. #include <sys/types.h>
  68. #include <sys/ipc.h>
  69. #include <sys/sem.h>
  70.  
  71. /*
  72.  * Exported procedures and variables of the sync module.
  73.  */
  74.     
  75. extern Sync_Instrument     sync_Instrument[MACH_MAX_NUM_PROCESSORS];
  76. extern Sync_Instrument    *sync_InstrumentPtr[MACH_MAX_NUM_PROCESSORS];
  77. extern int sync_BusyWaits;
  78.  
  79. extern void Sync_Init _ARGS_((void));
  80. extern ReturnStatus Sync_GetLock _ARGS_((Sync_Lock *lockPtr));
  81. extern ReturnStatus Sync_Unlock _ARGS_((Sync_Lock *lockPtr));
  82. extern ReturnStatus Sync_SlowLock _ARGS_((register Sync_Lock *lockPtr));
  83. extern Boolean Sync_SlowWait _ARGS_((Sync_Condition *conditionPtr, 
  84.             Sync_Lock *lockPtr, Boolean wakeIfSignal));
  85. extern ReturnStatus Sync_SlowBroadcast _ARGS_((unsigned int event, 
  86.             int *waitFlagPtr));
  87.  
  88. extern Boolean Sync_SlowMasterWait _ARGS_((unsigned int event,
  89.             Sync_Semaphore *mutexPtr, Boolean wakeIfSignal));
  90. extern void Sync_UnlockAndSwitch _ARGS_((Sync_Lock *lockPtr, Proc_State state));
  91. extern void Sync_WakeWaitingProcess _ARGS_((register Proc_ControlBlock *procPtr));
  92. extern void Sync_WakeupProcess _ARGS_((Timer_Ticks time, ClientData procAddress));
  93.  
  94. extern void Sync_GetWaitToken _ARGS_((Proc_PID *pidPtr, int *tokenPtr));
  95. extern void Sync_SetWaitToken _ARGS_((Proc_ControlBlock *procPtr, int waitToken));
  96.  
  97. extern Boolean Sync_WaitTime _ARGS_((Time time));
  98. extern Boolean Sync_WaitTimeInTicks _ARGS_((Timer_Ticks time));
  99. extern Boolean Sync_WaitTimeInterval _ARGS_((unsigned int interval));
  100.  
  101. extern Boolean Sync_ProcWait _ARGS_((Sync_Lock *lockPtr, Boolean wakeIfSignal));
  102. extern void Sync_ProcWakeup _ARGS_((Proc_PID pid, int token));
  103.  
  104. extern ReturnStatus Sync_RemoteNotify _ARGS_((Sync_RemoteWaiter *waitPtr));
  105. extern ReturnStatus Sync_RemoteNotifyStub _ARGS_((ClientData srvToken, 
  106.             int clientID, int command, Rpc_Storage *storagePtr));
  107.  
  108. extern ReturnStatus Sync_SlowLockStub _ARGS_((Sync_UserLock *lockPtr));
  109. extern ReturnStatus Sync_SlowWaitStub _ARGS_((unsigned int event, 
  110.             Sync_UserLock *lockPtr, Boolean wakeIfSignal));
  111. extern ReturnStatus Sync_SlowBroadcastStub _ARGS_((unsigned int event,
  112.                 int *waitFlagPtr));
  113.  
  114. extern void Sync_PrintStat _ARGS_((void));
  115.  
  116. extern void Sync_LockStatInit _ARGS_((void));
  117. extern void SyncAddPriorInt _ARGS_((int type, int *priorCountPtr, 
  118.             int *priorTypes, Address lockPtr, 
  119.             Proc_ControlBlock *pcbPtr));
  120.  
  121. extern void SyncDeleteCurrentInt _ARGS_((Address lockPtr, 
  122.                 Proc_ControlBlock *pcbPtr));
  123. extern void SyncMergePriorInt _ARGS_((int priorCount, int *priorTypes, 
  124.                 Sync_RegElement *regPtr));
  125. extern void Sync_RegisterInt _ARGS_((Address lock));
  126. extern void Sync_CheckoutInt _ARGS_((Address lock));
  127.  
  128. extern ReturnStatus Sync_SemgetStub _ARGS_((long key, int nsems, int semflg, 
  129.                     int *retValOut));
  130. extern ReturnStatus Sync_SemopStub _ARGS_((int semid, struct sembuf *sopsIn, 
  131.                     int nsops, int retValOut));
  132.  
  133. extern ReturnStatus Sync_SemctlStub _ARGS_((int semid, int semnum, int cmd, 
  134.                     union semun arg, int *retValOut));
  135. extern ReturnStatus Sync_SemStruct _ARGS_((int id, int *perm, 
  136.                        Sync_SysVSem **retPtr));
  137.  
  138. extern ReturnStatus Sync_Sleep _ARGS_((Time time));
  139. extern void Sync_SemInit _ARGS_((void));
  140.  
  141. extern ReturnStatus Sync_GetLockStats _ARGS_((int size, Address argPtr));
  142. extern ReturnStatus Sync_ResetLockStats _ARGS_((void));
  143.  
  144. extern void Sync_RemoveWaiter _ARGS_((Proc_ControlBlock *procPtr));
  145.  
  146. extern Sync_RegElement  *regQueuePtr;
  147.  
  148.  
  149.  
  150. /*
  151.  *----------------------------------------------------------------------------
  152.  *
  153.  * MASTER_LOCK --
  154.  *
  155.  *    Enter a critical section guarded by a binary semaphore.
  156.  *    This is for use in a multiprocessor environment
  157.  *    within the synchronization module, and in other
  158.  *    modules that interact with interrupt-time routines.
  159.  *    (All other synchronization should be done with Monitors.)
  160.  *    
  161.  *    Interrupts are disabled on the local processor to prevent
  162.  *    a preemptive context switch.  The semaphore is checked
  163.  *    with a Mach_TestAndSet atomic operation in a busy wait
  164.  *    to prevent races with other processors.
  165.  *
  166.  *     For uniprocessor debugging, panic when the lock is held (otherwise
  167.  *     we get an infinite loop).
  168.  *
  169.  *    There are three versions of this macro. This is due to the different
  170.  *    sizes of locks. There is only one uniprocessor version. It uses
  171.  *    other macros that are modified by compiler variables. There are
  172.  *    two versions of the multiprocessor implementation. The first is
  173.  *    used when we are keeping hit/miss ratios and the second is for
  174.  *    when we are not.
  175.  *
  176.  * Results:
  177.  *     None.
  178.  *
  179.  * Side effects:
  180.  *    The semaphore has its value set from 0 to 1.
  181.  *    Interrupts are disabled.
  182.  *
  183.  *----------------------------------------------------------------------------
  184.  */
  185.  
  186. #if (MACH_MAX_NUM_PROCESSORS == 1) /* uniprocessor implementation */
  187.  
  188. #define MASTER_LOCK(semaphore) \
  189.     { \
  190.         sync_Instrument[Mach_GetProcessorNumber()].numLocks++; \
  191.     DISABLE_INTR(); \
  192.     if ((semaphore)->value == 1) { \
  193.         SyncDeadlockPanic((semaphore)); \
  194.     } else { \
  195.         (semaphore)->value++;\
  196.         Sync_SemRegister(semaphore); \
  197.         Sync_RecordHit(semaphore); \
  198.         Sync_StoreDbgInfo(semaphore, TRUE); \
  199.         Sync_AddPrior(semaphore); \
  200.     }\
  201.     }
  202.  
  203. #else              /* multiprocessor implementation */
  204.  
  205. #ifdef LOCKREG
  206.  
  207. #define MASTER_LOCK(semaphore) \
  208.     { \
  209.     int missFlag = 0;\
  210.     int pnum = Mach_GetProcessorNumber();\
  211.     int type = ((semaphore)->type > 0) ? (semaphore)->type : 0;\
  212.         sync_InstrumentPtr[pnum]->numLocks++; \
  213.     DISABLE_INTR(); \
  214.     for(;;) { \
  215.         /* \
  216.          * wait until semaphore looks free -- avoid bouncing between \
  217.          * processor caches. \
  218.          */ \
  219.         while((semaphore)->value != 0) { \
  220.         if (missFlag == 0) { \
  221.             missFlag = 1; \
  222.         } \
  223.         sync_InstrumentPtr[pnum]->spinCount[type]++;\
  224.         } \
  225.         if(Mach_TestAndSet(&((semaphore)->value)) == 0) { \
  226.         break; \
  227.         } else if (missFlag == 0) { \
  228.         missFlag = 1; \
  229.         } \
  230.         sync_InstrumentPtr[pnum]->spinCount[type]++;\
  231.     } \
  232.     if(missFlag == 1) { \
  233.         Sync_RecordMiss(semaphore); \
  234.     } \
  235.     Sync_SemRegister(semaphore); \
  236.     Sync_RecordHit(semaphore) ; \
  237.     Sync_StoreDbgInfo(semaphore, TRUE); \
  238.     Sync_AddPrior(semaphore);    \
  239.     }
  240.  
  241. #else   /* LOCKREG -- These are the clean versions of the macros */
  242.  
  243. #define MASTER_LOCK(semaphore) \
  244.     { \
  245.         sync_InstrumentPtr[Mach_GetProcessorNumber()]->numLocks++; \
  246.     DISABLE_INTR(); \
  247.     for(;;) { \
  248.         /* \
  249.          * wait until semaphore looks free -- avoid bouncing between \
  250.          * processor caches. \
  251.          */ \
  252.         while((semaphore)->value != 0) { \
  253.         } \
  254.         if(Mach_TestAndSet(&((semaphore)->value)) == 0) { \
  255.         break; \
  256.         } \
  257.     } \
  258.     }
  259.  
  260. #endif /* LOCKREG */
  261. #endif /*multiprocessor implementation */
  262.  
  263.  
  264. /*
  265.  *----------------------------------------------------------------------------
  266.  *
  267.  * MASTER_UNLOCK --
  268.  *
  269.  *    Leave a critical section guarded by a binary semaphore.  This is for
  270.  *    use in a multiprocessor environment.  Interrupts are enabled and the
  271.  *    semaphore value is reset to 0 to allow other processors entry into
  272.  *    the critical section.
  273.  *
  274.  * Results:
  275.  *     None.
  276.  *
  277.  * Side effects:
  278.  *    The semaphore has its value reset to 0.
  279.  *    Interrupts are enabled.
  280.  *
  281.  *----------------------------------------------------------------------------
  282.  */
  283.  
  284. #define MASTER_UNLOCK(semaphore) \
  285.     { \
  286.     int pnum = Mach_GetProcessorNumber();\
  287.         sync_InstrumentPtr[pnum]->numUnlocks++; \
  288.     (semaphore)->value = 0; \
  289.     SyncDeleteCurrent(semaphore); \
  290.     if (!Mach_AtInterruptLevel()) { \
  291.         --mach_NumDisableIntrsPtr[pnum]; \
  292.         if (mach_NumDisableIntrsPtr[pnum] == 0) { \
  293.         Mach_EnableIntr(); \
  294.         } \
  295.     } \
  296.     }
  297.  
  298.  
  299. /* 
  300.  * Condition variables can be used in critical sections guarded by
  301.  * MASTER_LOCK and MASTER_UNLOCK.  Sync_MasterWait and
  302.  * Sync_MasterBroadcast are the analogues of Sync_Wait and
  303.  * Sync_Broadcast.
  304.  */
  305.  
  306. /*
  307.  *----------------------------------------------------------------------
  308.  *
  309.  * Sync_MasterWait --
  310.  *
  311.  *    Wait on an event with a master lock held.
  312.  *    This has the same semantics as Sync_Wait except
  313.  *    that the lock release when the process sleeps is
  314.  *    a master lock.
  315.  *
  316.  * Results:
  317.  *    None.
  318.  *
  319.  * Side effects:
  320.  *    The process gets descheduled, the master lock gets released
  321.  *    and then reacquired after the condition is notified.
  322.  *
  323.  *----------------------------------------------------------------------
  324.  */
  325.  
  326. #define Sync_MasterWait(conditionPtr, mutexPtr, wakeIfSignal) \
  327.     { \
  328.     (conditionPtr)->waiting = TRUE; \
  329.     (void) Sync_SlowMasterWait((unsigned int) conditionPtr, mutexPtr, \
  330.         wakeIfSignal); \
  331.     }
  332.  
  333. /*
  334.  *----------------------------------------------------------------------
  335.  *
  336.  * Sync_MasterBroadcast --
  337.  *
  338.  *    Notify an event, like Sync_Broadcast except it
  339.  *    should be used with a master lock held because of the
  340.  *    check on conditionPtr->waiting.
  341.  *
  342.  *    (This could verify that a master lock is held.)
  343.  *
  344.  * Results:
  345.  *    None.
  346.  *
  347.  * Side effects:
  348.  *    Notify all processes waiting on the event.
  349.  *
  350.  *----------------------------------------------------------------------
  351.  */
  352.  
  353. #define Sync_MasterBroadcast(conditionPtr) \
  354.     { \
  355.     if ((conditionPtr)->waiting == TRUE) { \
  356.         (void) Sync_SlowBroadcast((unsigned int)conditionPtr, \
  357.                 &(conditionPtr)->waiting); \
  358.     } \
  359.     }
  360.  
  361.  
  362. /*
  363.  *----------------------------------------------------------------------
  364.  *
  365.  * UNLOCK_AND_SWITCH --
  366.  *
  367.  *    Macro to call the internal routine to release the monitor lock and
  368.  *    then context switch.
  369.  *
  370.  * Results:
  371.  *    None.
  372.  *
  373.  * Side effects:
  374.  *    Lock released and process context switched.
  375.  *
  376.  *----------------------------------------------------------------------
  377.  */
  378.  
  379. #define UNLOCK_MONITOR_AND_SWITCH(state) Sync_UnlockAndSwitch(LOCKPTR, state)
  380.  
  381. /*
  382.  *    The initialization routines are used to initialize a semaphore.
  383.  *    The name parameter is the name of the semaphore and is used to
  384.  *    distinguish between types of locks. If you want the statistics
  385.  *    (hit, miss, etc) for two semaphores to be shared then give them the
  386.  *    same name. An example might be locks around file handles, where it
  387.  *    makes more sense to have the statistics for all the locks as a whole,
  388.  *    rather than just one lock. Also beware that no distinction is made
  389.  *    between locks and semaphores when determining types -- if they have
  390.  *    the same name they have the same type.
  391.  *       Sync_SemClear should be called when a semaphore is being deallocated
  392.  *    and will be no longer used. Currently all this routine does is to
  393.  *    take the statistics associated with the semaphore and merge them in
  394.  *    with those for the type as a whole.
  395.  */
  396.  
  397. /*
  398.  *----------------------------------------------------------------------
  399.  *
  400.  * Sync_SemRegister --
  401.  *
  402.  *     Register a semaphore.
  403.  *
  404.  *----------------------------------------------------------------------
  405.  */
  406. #define Sync_SemRegister Sync_LockRegister
  407.  
  408. /* 
  409.  *----------------------------------------------------------------------
  410.  *
  411.  * Sync_SemClear
  412.  * 
  413.  *     Clear a semaphore.
  414.  *
  415.  *----------------------------------------------------------------------
  416.  */
  417. #define Sync_SemClear Sync_LockClear
  418.  
  419.  
  420. /*
  421.  *----------------------------------------------------------------------
  422.  *
  423.  * Sync_SemInitStatic --
  424.  *
  425.  *    Initializes the fields of a semaphore in an initialization statement.
  426.  *    Ex:
  427.  *        static Sync_Semaphore foo = Sync_SemInitStatic("foo");
  428.  *
  429.  * Results:
  430.  *    None.
  431.  *
  432.  * Side effects:
  433.  *    None.
  434.  *
  435.  *----------------------------------------------------------------------
  436.  */
  437.  
  438. #ifdef CLEAN_LOCK
  439.  
  440. #define Sync_SemInitStatic(name) \
  441.     {0}
  442.  
  443. #else
  444. #ifdef LOCKDEP
  445.  
  446. #define Sync_SemInitStatic(name) \
  447.     {0,0,0, SYNC_SEMAPHORE, 0, SYNC_LISTINFO_INIT, name,(Address) NIL, \
  448.      (Proc_ControlBlock *) NIL, 0}
  449.  
  450. #else
  451.  
  452. #ifdef LOCKREG
  453.  
  454. #define Sync_SemInitStatic(name) \
  455.     {0,0,0, SYNC_SEMAPHORE, 0, SYNC_LISTINFO_INIT, name,(Address) NIL, \
  456.      (Proc_ControlBlock *) NIL}
  457. #else
  458. #define Sync_SemInitStatic(name) \
  459.     {0,name, (Address) NIL, (Proc_ControlBlock *) NIL}
  460.  
  461. #endif /* LOCKREG */
  462. #endif /* LOCKDEP */
  463. #endif /* CLEAN_LOCK */
  464.  
  465.  
  466. /*
  467.  *----------------------------------------------------------------------
  468.  *
  469.  * Sync_SemInitDynamic --
  470.  *
  471.  *    Initializes the fields of a semaphore during program execution.
  472.  *    Ex:
  473.  *        Sync_SemInitDynamic(foo,"foo");
  474.  *
  475.  * Results:
  476.  *    None.
  477.  *
  478.  * Side effects:
  479.  *    None.
  480.  *
  481.  *----------------------------------------------------------------------
  482.  */
  483.  
  484. #ifdef CLEAN_LOCK
  485.  
  486. #define Sync_SemInitDynamic(sem,semName) \
  487.     { (sem)->value = 0; }
  488.  
  489. #else
  490. #ifdef LOCKDEP
  491.  
  492. #define Sync_SemInitDynamic(sem, semName) { \
  493.     (sem)->value = (sem)->miss = 0; (sem)->name = semName; \
  494.     (sem)->hit = 0; (sem)->type = 0; \
  495.     (sem)->holderPC = (Address)NIL; (sem)->class = SYNC_SEMAPHORE;\
  496.     (sem)->holderPCBPtr = (Proc_ControlBlock *) NIL; \
  497.     (sem)->priorCount = 0;\
  498. }
  499.  
  500.  
  501. #else
  502.  
  503. #ifdef LOCKREG
  504.  
  505. #define Sync_SemInitDynamic(sem, semName) { \
  506.     (sem)->value = (sem)->miss = 0; (sem)->name = semName; \
  507.     (sem)->hit = 0; (sem)->type = 0;\
  508.     (sem)->holderPC = (Address)NIL; (sem)->class = SYNC_SEMAPHORE;\
  509.     (sem)->holderPCBPtr = (Proc_ControlBlock *) NIL; \
  510. }
  511.  
  512. #else
  513. #define Sync_SemInitDynamic(sem, semName) { \
  514.     (sem)->value = 0; (sem)->name = semName; \
  515.     (sem)->holderPC = (Address)NIL;\
  516.     (sem)->holderPCBPtr = (Proc_ControlBlock *) NIL; \
  517. }
  518. #endif /* LOCKREG */
  519. #endif /* LOCKDEP */
  520. #endif /* CLEAN_LOCK */
  521.  
  522.  
  523. /*
  524.  *----------------------------------------------------------------------
  525.  *
  526.  * Sync_LockInitStatic --
  527.  *
  528.  *    Initializes the fields of a lock in an initialization statement.
  529.  *    Ex:
  530.  *        static Sync_Lock foo = Sync_LockInitStatic("foo");
  531.  *
  532.  * Results:
  533.  *    None.
  534.  *
  535.  * Side effects:
  536.  *    None.
  537.  *
  538.  *----------------------------------------------------------------------
  539.  */
  540. #ifdef CLEAN_LOCK
  541.  
  542. #define Sync_LockInitStatic(name) {0,0}
  543.  
  544. #else
  545. #ifdef LOCKDEP
  546.  
  547. #define Sync_LockInitStatic(name) \
  548.     {0,0,0,SYNC_LOCK, 0, SYNC_LISTINFO_INIT, 0, name, (Address) NIL, \
  549.      (Proc_ControlBlock *) NIL,0}
  550.  
  551. #else
  552.  
  553. #ifdef LOCKREG
  554.  
  555. #define Sync_LockInitStatic(name) \
  556.     {0,0,0,SYNC_LOCK, 0, SYNC_LISTINFO_INIT, 0, name, (Address) NIL, \
  557.      (Proc_ControlBlock *) NIL}
  558.  
  559. #else
  560. #define Sync_LockInitStatic(name) \
  561.     {0,0,name, (Address) NIL, (Proc_ControlBlock *) NIL}
  562.  
  563.  
  564. #endif /* LOCKREG */
  565. #endif /* LOCKDEP */
  566. #endif /* CLEAN_LOCK */
  567.  
  568.  
  569. /*
  570.  *----------------------------------------------------------------------
  571.  *
  572.  * Sync_LockInitDynamic --
  573.  *
  574.  *    Initializes the fields of a lock during program execution.
  575.  *    Ex:
  576.  *        Sync_LockInitDynamic(foo,"foo");
  577.  *
  578.  * Results:
  579.  *    None.
  580.  *
  581.  * Side effects:
  582.  *    None.
  583.  *
  584.  *----------------------------------------------------------------------
  585.  */
  586.  
  587. #ifdef CLEAN_LOCK
  588.  
  589. #define Sync_LockInitDynamic(lock, lockName) \
  590.     {(lock)->inUse = (lock)->waiting = 0;}
  591.  
  592. #else
  593. #ifdef LOCKDEP
  594.  
  595. #define Sync_LockInitDynamic(lock, lockName) { \
  596.     (lock)->inUse = (lock)->waiting = 0; (lock)->class = SYNC_LOCK;\
  597.     (lock)->hit = (lock)->miss = 0; (lock)->name = lockName; \
  598.     (lock)->holderPC = (Address) NIL; (lock)->type = 0; \
  599.     (lock)->holderPCBPtr  = (Proc_ControlBlock *) NIL; \
  600.     (lock)->priorCount = 0;\
  601.  
  602. #else
  603.  
  604. #ifdef LOCKREG
  605.  
  606. #define Sync_LockInitDynamic(lock, lockName) { \
  607.     (lock)->inUse = (lock)->waiting = 0; (lock)->class = SYNC_LOCK;\
  608.     (lock)->hit = (lock)->miss = 0; (lock)->name = lockName; \
  609.     (lock)->holderPC = (Address) NIL; (lock)->type = 0; \
  610.     (lock)->holderPCBPtr  = (Proc_ControlBlock *) NIL; \
  611. }
  612.  
  613. #else
  614. #define Sync_LockInitDynamic(lock, lockName) { \
  615.     (lock)->inUse = (lock)->waiting = 0;  (lock)->name = lockName; \
  616.     (lock)->holderPC = (Address) NIL; \
  617.     (lock)->holderPCBPtr  = (Proc_ControlBlock *) NIL; \
  618. }
  619.  
  620. #endif /* LOCKREG */
  621. #endif /* LOCKDEP */
  622. #endif /* CLEAN_LOCK */
  623.  
  624.  
  625. /*
  626.  *----------------------------------------------------------------------
  627.  *
  628.  * Sync_IsRegistered --
  629.  *
  630.  *    Returns true if a lock or semaphore has already been registered. If
  631.  *    LOCKREG is not defined then this macro always returns FALSE.
  632.  *
  633.  * Results:
  634.  *    TRUE if lock or semaphore registered.
  635.  *
  636.  * Side effects:
  637.  *    None.
  638.  *
  639.  *----------------------------------------------------------------------
  640.  */
  641.  
  642. #ifdef LOCKREG
  643.  
  644. #define Sync_IsRegistered(lock) \
  645.     (((lock)->type > 0) ? TRUE : FALSE)
  646.  
  647. #else /* LOCKREG */
  648.  
  649. #define Sync_IsRegistered(lock) FALSE
  650.  
  651. #endif /* LOCKREG */
  652.  
  653. /*
  654.  *----------------------------------------------------------------------
  655.  *
  656.  * Sync_LockRegister --
  657.  *
  658.  *    Used to add a lock to the registration database.
  659.  *    If LOCKREG is not defined then this macro does nothing.
  660.  *
  661.  * Results:
  662.  *    None.
  663.  *
  664.  * Side effects:
  665.  *    The lock is registered.
  666.  *
  667.  *----------------------------------------------------------------------
  668.  */
  669. #ifdef LOCKREG
  670.  
  671. #define Sync_LockRegister(lock) \
  672.     { \
  673.     if (!Sync_IsRegistered((Sync_Lock *) lock)) { \
  674.         Sync_RegisterInt((Address) (lock)); \
  675.     } \
  676.     }
  677.  
  678. #else /* LOCKREG */
  679.  
  680. #define Sync_LockRegister(lock) {}
  681.  
  682. #endif /* LOCKREG */
  683.  
  684.  
  685.  
  686. /*
  687.  *----------------------------------------------------------------------
  688.  *
  689.  * Sync_LockClear --
  690.  *
  691.  *    Used to clear and deregister a lock before it is freed.
  692.  *    If LOCKREG is not defined then this macro does nothing.
  693.  *
  694.  * Results:
  695.  *    None.
  696.  *
  697.  * Side effects:
  698.  *    The lock is deregistered.
  699.  *
  700.  *----------------------------------------------------------------------
  701.  */
  702. #ifdef LOCKREG
  703.  
  704. #define Sync_LockClear(lock) \
  705.     { \
  706.     if (Sync_IsRegistered(lock)) { \
  707.         Sync_CheckoutInt((Address) (lock)); \
  708.     } \
  709.     }
  710.  
  711. #else /* LOCKREG */
  712.  
  713. #define Sync_LockClear(sem) 
  714.  
  715. #endif /* LOCKREG */
  716.  
  717. /*
  718.  *----------------------------------------------------------------------
  719.  *
  720.  * Sync_AddPrior --
  721.  *
  722.  *    When a lock is grabbed the prior lock must be added to the prior
  723.  *    types for the lock.
  724.  *    This macro does nothing if LOCKDEP is not defined.
  725.  *
  726.  * Results:
  727.  *    None.
  728.  *
  729.  * Side effects:
  730.  *    None.
  731.  *
  732.  *----------------------------------------------------------------------
  733.  */
  734.  
  735. #ifdef LOCKDEP
  736.  
  737. #define Sync_AddPrior(lockPtr) { \
  738.     Sync_AddPriorInt((lockPtr)->type, &(lockPtr)->priorCount, \
  739.     (lockPtr)->priorTypes, (lockPtr), (lockPtr)->holderPCBPtr);  \
  740. }
  741.  
  742. #else /* LOCKDEP */
  743.  
  744. #define Sync_AddPrior(lockPtr)
  745.  
  746. #endif /* LOCKDEP */
  747.  
  748. /*
  749.  *----------------------------------------------------------------------
  750.  *
  751.  * SyncMergePrior --
  752.  *
  753.  *    When a lock is cleared its statistics must be added to those for
  754.  *    the type as a whole.
  755.  *    This macro does nothing if LOCKDEP is not defined.
  756.  *
  757.  * Results:
  758.  *    None.
  759.  *
  760.  * Side effects:
  761.  *    None.
  762.  *
  763.  *----------------------------------------------------------------------
  764.  */
  765.  
  766. #ifdef LOCKDEP
  767.  
  768. #define SyncMergePrior(lockPtr, regPtr) \
  769.     { SyncMergePriorInt((lockPtr)->priorCount, (lockPtr)->priorTypes, \
  770.                (regPtr)); } 
  771.  
  772. #else /* LOCKDEP */
  773.  
  774. #define SyncMergePrior(lockPtr, regPtr)
  775.  
  776. #endif /* LOCKDEP */
  777.  
  778.  
  779. /*
  780.  *----------------------------------------------------------------------
  781.  *
  782.  * SyncDeleteCurrent --
  783.  *
  784.  *    When we unlock a lock we have to delete it from the stack of 
  785.  *    current locks.
  786.  *    If LOCKDEP is not defined then don't do anything.
  787.  *
  788.  * Results:
  789.  *    None.
  790.  *
  791.  * Side effects:
  792.  *    The lock is removed from the lock stack in the current pcb.
  793.  *
  794.  *----------------------------------------------------------------------
  795.  */
  796.  
  797. #ifdef LOCKDEP
  798.  
  799. #define SyncDeleteCurrent(lockPtr) \
  800.     { SyncDeleteCurrentInt((lockPtr), (lockPtr)->holderPCBPtr); }
  801.  
  802. #else /* LOCKDEP */
  803.  
  804. #define SyncDeleteCurrent(lockPtr) 
  805.  
  806. #endif /* LOCKDEP */
  807.  
  808.  
  809. /*
  810.  *----------------------------------------------------------------------
  811.  *
  812.  * SyncDeadlockPanic --
  813.  *
  814.  *    Prints out a warning message and calls panic. There is one
  815.  *    version for clean locks, and another version for printing
  816.  *    debugging information found in the locks.
  817.  *
  818.  * Results:
  819.  *    None.
  820.  *
  821.  * Side effects:
  822.  *    panic is called.
  823.  *
  824.  *----------------------------------------------------------------------
  825.  */
  826.  
  827. #ifdef CLEAN_LOCK
  828.  
  829. #define SyncDeadlockPanic(semaphore) { \
  830.         panic("Deadlock!!! (semaphore @ 0x%x)\n", (int)(semaphore)); \
  831. }
  832.  
  833. #else /* CLEAN_LOCK */
  834.  
  835. #define SyncDeadlockPanic(semaphore) { \
  836.         panic("Deadlock!!!(%s @ 0x%x)\nHolder PC: 0x%x Current PC: 0x%x\nHolder PCB @ 0x%x Current PCB @ 0x%x\n", \
  837.         (semaphore)->name,(int)(semaphore),(int)(semaphore)->holderPC,\
  838.         (int) Mach_GetPC(),(int) (semaphore)->holderPCBPtr, \
  839.         (int) Proc_GetCurrentProc()); \
  840. }
  841.  
  842. #endif /* CLEAN_LOCK */
  843.  
  844. /*
  845.  *----------------------------------------------------------------------
  846.  *
  847.  * Sync_RecordHit --
  848.  *
  849.  *    If LOCKREG is defined then the hit field of the lock
  850.  *    is incremented.
  851.  *
  852.  * Results:
  853.  *    None.
  854.  *
  855.  * Side effects:
  856.  *    None.
  857.  *
  858.  *----------------------------------------------------------------------
  859.  */
  860.  
  861. #ifndef LOCKREG 
  862.  
  863. #define Sync_RecordHit(lock) {}
  864.  
  865. #else /* LOCKREG */
  866.  
  867. #define Sync_RecordHit(lock) {    (lock)->hit++; }
  868.  
  869. #endif /* LOCKREG */
  870.  
  871. /*
  872.  *----------------------------------------------------------------------
  873.  *
  874.  * Sync_RecordMiss --
  875.  *
  876.  *    If LOCKREG is defined then the miss field of the lock
  877.  *    is incremented.
  878.  *
  879.  * Results:
  880.  *    None.
  881.  *
  882.  * Side effects:
  883.  *    None.
  884.  *
  885.  *----------------------------------------------------------------------
  886.  */
  887. #ifndef LOCKREG
  888.  
  889. #define Sync_RecordMiss(lock) {}
  890.  
  891. #else /* LOCKREG */
  892.  
  893. #define Sync_RecordMiss(lock) { (lock)->miss++; }
  894.  
  895. #endif /* LOCKREG */
  896.  
  897. /*
  898.  *----------------------------------------------------------------------
  899.  *
  900.  * SyncStorDbgInfo --
  901.  *
  902.  *    If CLEAN_LOCK isn't defined then store debugging information
  903.  *    in the lock.  If "lockedByMacro" is TRUE, the lock was obtained
  904.  *    via a macro, so we record the current PC, which is in the
  905.  *    function that invoked the macro.  If it's FALSE, the lock was
  906.  *    obtained by a function whose sole job is to obtain the lock,
  907.  *    so we want to record the PC of that function's caller.
  908.  *
  909.  * Results:
  910.  *    None.
  911.  *
  912.  * Side effects:
  913.  *    None.
  914.  *
  915.  *----------------------------------------------------------------------
  916.  */
  917. #ifdef CLEAN_LOCK
  918.  
  919. #define Sync_StoreDbgInfo(semaphore, lockedByMacro) {}
  920.  
  921. #else /* CLEAN_LOCK */
  922.  
  923. #define Sync_StoreDbgInfo(semaphore, lockedByMacro) {             \
  924.     if ((lockedByMacro) == TRUE) {                    \
  925.     (semaphore)->holderPC = (Address) Mach_GetPC();         \
  926.     } else {                                \
  927.     (semaphore)->holderPC = (Address) Mach_GetCallerPC();         \
  928.     }                                    \
  929.     (semaphore)->holderPCBPtr = Proc_GetCurrentProc();     \
  930. }
  931.  
  932. #endif /* CLEAN_LOCK */
  933. #endif /* _SYNC */
  934.  
  935.